#include "common.h"

#include "titlestate.h"

#ifdef _DEBUG
#define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
#define new DEBUG_NEW
#endif

LogoState::LogoState()
:	GameState( GM_LOGO )
,	_alpha( 0 )
,	_hold( false )
,	_holdForThisTime( 2.0f )
,	_isFadeOut( false )
,	_logoPos( D3DXVECTOR3( 0, 0, 0 ) )
,	_timeOffset( 0 )
,	_pSprite( NULL )
,	_pLogoTexture( NULL )
{
}

void LogoState::ChangeState( GameState** currentState, eGameMode nextState )
{
	if( (*currentState)->GetCurrentState() == nextState )
	{
		return;
	}

	(*currentState)->Release();
	*currentState = new TitleState();

	assert( *currentState != NULL );
	(*currentState)->Initialize();

	return;
}

bool LogoState::Initialize( void* info )
{
	Core& core = Core::GetInstance();

	// Direct3d Initialize
	D3DDISPLAYMODE d3ddm = {0};
	if( FAILED( core.GetD3d()->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
	{
		// error
		assert( false );
	}
	
	D3DPRESENT_PARAMETERS d3dpp = {0};
	d3dpp.BackBufferWidth			= core.GetClientSizeX();
	d3dpp.BackBufferHeight			= core.GetClientSizeY();
	d3dpp.BackBufferCount			= 1;
	d3dpp.MultiSampleType			= D3DMULTISAMPLE_NONE;
	d3dpp.SwapEffect				= D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow				= core.GetWindowHandle();
	d3dpp.EnableAutoDepthStencil	= TRUE;
	d3dpp.AutoDepthStencilFormat	= D3DFMT_D24S8;
	d3dpp.BackBufferFormat			= d3ddm.Format;
	d3dpp.Windowed					= TRUE;
	d3dpp.PresentationInterval		= D3DPRESENT_INTERVAL_IMMEDIATE;

	LPDIRECT3DDEVICE9 device;
	if( FAILED( core.GetD3d()->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		//D3DDEVTYPE_REF,
		core.GetWindowHandle(),
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp,
		&device ) ) )
	{
		// error
		assert( false );
	}

	// Logo
	device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
	device->SetRenderState( D3DRS_LIGHTING, FALSE );
	device->SetRenderState( D3DRS_ZENABLE, TRUE );

	D3DXCreateSprite( device, &_pSprite );
	WCHAR filePath[50];
	GetPrivateProfileString( L"Logo", L"FilePath", L"", filePath, 50, gGameSettingsFilePath );
	if( FAILED( D3DXCreateTextureFromFile( device, filePath, &_pLogoTexture ) ) )
	{
		// error
		assert( false );
	}

	int width		= GetPrivateProfileInt( L"Logo", L"Width", 0, gGameSettingsFilePath );
	int height		= GetPrivateProfileInt( L"Logo", L"Height", 0, gGameSettingsFilePath );
	int holdTime	= GetPrivateProfileInt( L"Logo", L"LogoHoldTime", 0, gGameSettingsFilePath );
	int fadeTime	= GetPrivateProfileInt( L"Logo", L"FadeTime", 0, gGameSettingsFilePath );
	int textOffset	= GetPrivateProfileInt( L"Logo", L"TextOffset", 0, gGameSettingsFilePath );

	_holdForThisTime = holdTime / 1000.0f;
	_totalFadeTime	 = fadeTime / 1000.0f; 

	_logoPos.x = static_cast< float >( ( core.GetClientSizeX() - width ) / 2 );
	_logoPos.y = static_cast< float >( ( core.GetClientSizeY() - height ) / 2 - textOffset );

	core.SetD3dDevice( &device );
	this->Initialized();

	return true;
}

LRESULT LogoState::MessageHandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_DESTROY :
		Core::GetInstance().PrepareToQuit();
		break;
	}
	return DefWindowProc( hWnd, msg, wParam, lParam );
}

void LogoState::Run( GameState** currentState, float time )
{
	assert( this->IsInitialized() );
	
	LPDIRECT3DDEVICE9 device = Core::GetInstance().GetD3dDevice();

	if( _hold )
	{
		_holdForThisTime -= time;
		_hold = ( _holdForThisTime <= 0.0f )? false : true;
		return;
	}

	device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFF000000, 1.0f, 0 );

	if( FAILED( device->BeginScene() ) )
	{
		return;
	}

	_timeOffset += ( _isFadeOut )? -time : time;

	BYTE alpha;
	if( SUCCEEDED(_pSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE ) ) )
	{
		 alpha = static_cast< BYTE >( 0xFF * ( _timeOffset / _totalFadeTime ) );
		_pSprite->Draw( _pLogoTexture, NULL, NULL, &_logoPos, D3DCOLOR_ARGB( alpha, 0xFF, 0xFF, 0xFF ) );

		_pSprite->End();
	}

	if( alpha >= 0xFF )
	{
		_isFadeOut = true;
		_hold = true;
	}

	device->EndScene();

	device->Present( NULL, NULL, NULL, NULL );

	if( _isFadeOut == true && _timeOffset <= 0.0f )
	{
		ChangeState( currentState, GM_TITLE );
	}
}

void LogoState::Release()
{
	if( _pSprite )
	{
		_pSprite->Release();
	}
	if( _pLogoTexture )
	{
		_pLogoTexture->Release();
	}
	delete this;
}

